﻿using HtmlAgilityPack;
using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Text;

namespace MVBuddy.Common.Helpers
{
    public class HtmlRequest
    {
        private HttpWebRequest webRequest;

        public Uri Uri { get; set; }
        public string Method { get; set; }
        public string ContentType { get; set; }
        public Dictionary<string, string> Parameters { get; private set; }
        public event EventHandler<HtmlRequestCompletedEventArgs> HtmlRequestCompleted;

        public HtmlRequest(Uri uri)
            : this(uri, "GET", string.Empty, new Dictionary<string, string>())
        {
        }

        public HtmlRequest(Uri uri, string method, string contentType, Dictionary<string, string> parameters)
        {
            this.Uri = uri;
            this.Method = method;
            this.ContentType = contentType;
            this.Parameters = parameters;
        }

        public void DoRequest()
        {
            this.webRequest = (HttpWebRequest)HttpWebRequest.CreateHttp(this.Uri);
            this.webRequest.Method = this.Method;
            this.webRequest.ContentType = this.ContentType;
            this.webRequest.CookieContainer = new CookieContainer();

            if (this.Method == "GET")
            {
                webRequest.BeginGetResponse(new AsyncCallback(GetResponseCallback), this);
            }
            else
            {
                webRequest.BeginGetRequestStream(new AsyncCallback(GetRequestStreamCallback), this);
            }
        }

        private static void GetRequestStreamCallback(IAsyncResult asynchronousResult)
        {
            HtmlRequest htmlRequest = (HtmlRequest)asynchronousResult.AsyncState;

            // End the operation
            Stream postStream = htmlRequest.webRequest.EndGetRequestStream(asynchronousResult);

            string postData = string.Empty;
            int count = 0;

            foreach (KeyValuePair<string, string> kvp in htmlRequest.Parameters)
            {
                postData += kvp.Key + "=" + kvp.Value;

                if (++count < htmlRequest.Parameters.Count)
                {
                    postData += "&";
                }
            }

            // Convert the string into a byte array. 
            byte[] byteArray = Encoding.UTF8.GetBytes(postData);

            // Write to the request stream.
            postStream.Write(byteArray, 0, byteArray.Length);
            postStream.Close();

            // Start the asynchronous operation to get the response
            htmlRequest.webRequest.BeginGetResponse(new AsyncCallback(GetResponseCallback), htmlRequest);
        }

        private static void GetResponseCallback(IAsyncResult asynchronousResult)
        {
            HtmlRequest htmlRequest = (HtmlRequest)asynchronousResult.AsyncState;

            // End the operation
            HttpWebResponse response = (HttpWebResponse)htmlRequest.webRequest.EndGetResponse(asynchronousResult);
            Stream streamResponse = response.GetResponseStream();
            StreamReader streamRead = new StreamReader(streamResponse);
            string responseString = streamRead.ReadToEnd();
            // Close the stream object
            streamResponse.Close();
            streamRead.Close();

            // Release the HttpWebResponse
            response.Close();

            HtmlDocument document = new HtmlDocument();
            document.LoadHtml(responseString);

            if (htmlRequest.HtmlRequestCompleted != null)
            {
                htmlRequest.HtmlRequestCompleted(htmlRequest, new HtmlRequestCompletedEventArgs(document));
                htmlRequest.HtmlRequestCompleted = null;
            }
        }
    }
}